//
// Created by hy on 2018/9/3.
//
#include "hisemaphore.h"
#include "himutex.h"
#include <time.h>
#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

HiSemaphore::HiSemaphore() {
    pthread_cond_init(&m_semaphore, NULL);
}

HiSemaphore::~HiSemaphore() {
    pthread_cond_destroy(&m_semaphore);
}

int HiSemaphore::broadcast() {
    return pthread_cond_broadcast(&m_semaphore);
}

int HiSemaphore::wait(HiMutex &AMutex) {
    return pthread_cond_wait(&m_semaphore, &AMutex.lock_);
}

int HiSemaphore::wait_timeout(HiMutex &AMutex, int ms) {
    int retval;
    struct timeval delta;
    struct timespec abstime;

    gettimeofday(&delta, NULL);

    abstime.tv_sec = delta.tv_sec + (ms / 1000);
    abstime.tv_nsec = (delta.tv_usec + (ms % 1000) * 1000) * 1000;
    if (abstime.tv_nsec > 1000000000) {
        abstime.tv_sec += 1;
        abstime.tv_nsec -= 1000000000;
    }

    while (1) {
        retval = pthread_cond_timedwait(&m_semaphore, &AMutex.lock_, &abstime);
        if (retval == 0)
            return 0;
        else if (retval == EINTR)
            continue;
        else if (retval == ETIMEDOUT)
            return 1;
        else
            break;
    }

    return -1;
}

int HiSemaphore::singal() {
    return pthread_cond_signal(&m_semaphore);
}
